package com.apigen.platform.controller;

import com.apigen.platform.common.Result;
import com.apigen.platform.dto.CodeGenerationRequest;
import com.apigen.platform.service.ICodeGenerationService;
import com.apigen.platform.service.EnhancedCodeGenerationService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.io.File;
import java.util.Map;

/**
 * 代码生成控制器
 *
 * @author API Generator Platform
 * @since 2024-09-24
 */
@Slf4j
@RestController
@RequestMapping("/api/code-generation")
@RequiredArgsConstructor
@Validated
@Tag(name = "代码生成", description = "项目代码生成、预览、下载等功能接口")
public class CodeGenerationController {

    private final ICodeGenerationService codeGenerationService;
    private final EnhancedCodeGenerationService enhancedCodeGenerationService;

    @PostMapping("/generate")
    @Operation(summary = "生成项目代码", description = "根据配置参数生成完整的项目代码")
    public Result<Map<String, Object>> generateCode(@Valid @RequestBody CodeGenerationRequest request) {
        try {
            Map<String, Object> result = codeGenerationService.generateProject(request);
            if ((Boolean) result.getOrDefault("success", false)) {
                return Result.success(result);
            } else {
                return Result.error((String) result.get("message"));
            }
        } catch (Exception e) {
            log.error("生成项目代码失败: {}", e.getMessage());
            return Result.error("生成代码失败: " + e.getMessage());
        }
    }

    @PostMapping("/preview")
    @Operation(summary = "预览生成代码", description = "预览将要生成的代码内容，不实际生成项目")
    public Result<Map<String, Object>> previewCode(@Valid @RequestBody CodeGenerationRequest request) {
        try {
            Map<String, Object> result = codeGenerationService.previewCode(request);
            return Result.success(result);
        } catch (Exception e) {
            log.error("预览生成代码失败: {}", e.getMessage());
            return Result.error("预览代码失败: " + e.getMessage());
        }
    }

    @GetMapping("/frameworks")
    @Operation(summary = "获取支持的框架", description = "获取系统支持的所有代码生成框架类型")
    public Result<Map<String, Object>> getSupportedFrameworks() {
        try {
            Map<String, Object> frameworks = codeGenerationService.getSupportedFrameworks();
            return Result.success(frameworks);
        } catch (Exception e) {
            log.error("获取支持的框架失败: {}", e.getMessage());
            return Result.error("获取框架列表失败: " + e.getMessage());
        }
    }

    @GetMapping("/template-config/{frameworkType}")
    @Operation(summary = "获取模板配置", description = "获取指定框架类型的模板配置信息")
    public Result<Map<String, Object>> getTemplateConfig(
            @Parameter(description = "框架类型") @PathVariable String frameworkType) {
        try {
            Map<String, Object> config = codeGenerationService.getTemplateConfig(frameworkType);
            return Result.success(config);
        } catch (Exception e) {
            log.error("获取模板配置失败: {}", e.getMessage());
            return Result.error("获取模板配置失败: " + e.getMessage());
        }
    }

    @PostMapping("/validate")
    @Operation(summary = "验证生成配置", description = "验证代码生成配置参数的有效性")
    public Result<Map<String, Object>> validateConfig(@Valid @RequestBody CodeGenerationRequest request) {
        try {
            Map<String, Object> result = codeGenerationService.validateConfig(request);
            return Result.success(result);
        } catch (Exception e) {
            log.error("验证生成配置失败: {}", e.getMessage());
            return Result.error("验证配置失败: " + e.getMessage());
        }
    }

    @GetMapping("/history")
    @Operation(summary = "获取生成历史", description = "分页获取项目的代码生成历史记录")
    public Result<Map<String, Object>> getGenerationHistory(
            @Parameter(description = "项目ID") @RequestParam Long projectId,
            @Parameter(description = "当前页", example = "1") @RequestParam(defaultValue = "1") Long current,
            @Parameter(description = "每页大小", example = "10") @RequestParam(defaultValue = "10") Long size) {
        try {
            Map<String, Object> result = codeGenerationService.getGenerationHistory(projectId, current, size);
            return Result.success(result);
        } catch (Exception e) {
            log.error("获取生成历史失败: {}", e.getMessage());
            return Result.error("获取历史记录失败: " + e.getMessage());
        }
    }

    @GetMapping("/download/{generationId}")
    @Operation(summary = "下载生成的代码", description = "下载指定生成记录的代码包")
    public ResponseEntity<Resource> downloadGeneratedCode(
            @Parameter(description = "生成记录ID") @PathVariable String generationId) {
        try {
            Map<String, Object> downloadInfo = enhancedCodeGenerationService.downloadProject(generationId);
            
            if (!(Boolean) downloadInfo.get("success")) {
                return ResponseEntity.notFound().build();
            }
            
            String filePath = (String) downloadInfo.get("filePath");
            String fileName = (String) downloadInfo.get("fileName");
            
            File file = new File(filePath);
            if (!file.exists()) {
                return ResponseEntity.notFound().build();
            }
            
            Resource resource = new FileSystemResource(file);
            
            return ResponseEntity.ok()
                    .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + fileName + "\"")
                    .contentType(MediaType.APPLICATION_OCTET_STREAM)
                    .contentLength(file.length())
                    .body(resource);
                    
        } catch (Exception e) {
            log.error("下载生成代码失败: {}", e.getMessage());
            return ResponseEntity.internalServerError().build();
        }
    }

    @PostMapping("/generate-project")
    @Operation(summary = "生成完整项目", description = "根据配置生成完整的Spring Boot项目")
    public Result<Map<String, Object>> generateProject(@Valid @RequestBody CodeGenerationRequest request) {
        try {
            Map<String, Object> result = enhancedCodeGenerationService.generateProject(request);
            return Result.success(result);
        } catch (Exception e) {
            log.error("生成完整项目失败: {}", e.getMessage());
            return Result.error("生成项目失败: " + e.getMessage());
        }
    }

    @PostMapping("/preview-project")
    @Operation(summary = "预览项目代码", description = "预览将要生成的完整项目代码")
    public Result<Map<String, Object>> previewProject(@Valid @RequestBody CodeGenerationRequest request) {
        try {
            Map<String, Object> result = enhancedCodeGenerationService.previewCode(request);
            return Result.success(result);
        } catch (Exception e) {
            log.error("预览项目代码失败: {}", e.getMessage());
            return Result.error("预览代码失败: " + e.getMessage());
        }
    }

    @PostMapping("/generate-table/{tableId}")
    @Operation(summary = "生成单表代码", description = "为指定表生成代码")
    public Result<Map<String, Object>> generateTableCode(
            @Parameter(description = "表ID") @PathVariable Long tableId,
            @Valid @RequestBody CodeGenerationRequest request) {
        try {
            Map<String, Object> result = enhancedCodeGenerationService.generateTableCode(request, tableId);
            return Result.success(result);
        } catch (Exception e) {
            log.error("生成单表代码失败: {}", e.getMessage());
            return Result.error("生成代码失败: " + e.getMessage());
        }
    }

    @DeleteMapping("/cleanup/{generationId}")
    @Operation(summary = "清理临时文件", description = "清理生成过程中的临时文件")
    public Result<Void> cleanupTempFiles(@Parameter(description = "生成记录ID") @PathVariable String generationId) {
        try {
            Boolean success = enhancedCodeGenerationService.cleanupTempFiles(generationId);
            if (success) {
                return Result.success("清理成功");
            } else {
                return Result.error("清理失败");
            }
        } catch (Exception e) {
            log.error("清理临时文件失败: {}", e.getMessage());
            return Result.error("清理失败: " + e.getMessage());
        }
    }
}











